﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HandyControl.Controls;
using HandyControl.Data;
using HandyControl.Tools.Extension;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using ZeroBug.EasyFlow.Communication;
using ZeroBug.EasyFlow.Core;
using ZeroBug.EasyFlow.Machine;
using ZeroBug.EasyFlow.Motion;

namespace EasyFlow
{
    public partial class MainWindowViewModel : ObservableObject
    {
        private VariableTreeView _variableTreeView;
        private Dictionary<string, ObservableCollection<StepViewModel>> flowEntranceStepViewModels;
        [ObservableProperty]
        ObservableCollection<FlowViewModel> _flowViewModels;
        [ObservableProperty]
        ObservableCollection<StepViewModel> _entranceStepViewModel;
        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(AddFlowCommand))]
        [NotifyCanExecuteChangedFor(nameof(RemoveFlowCommand))]
        bool _isAllowEdit = true;
        [ObservableProperty]
        FlowViewModel _currentSelectedFlow;
        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(flowPauseCommand))]
        bool _canPauseExecute;
        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(flowStartCommand))]
        bool _canStartExecute = true;
        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(flowStopCommand))]
        bool _canStopExecute;
        [ObservableProperty]
        [NotifyCanExecuteChangedFor(nameof(flowStepCommand))]
        bool _canStepExecute = true;
        [ObservableProperty]
        ObservableCollection<StepInfoGroup> _stepGroups;
        Step _currentMouseDragOverStep;
        StepViewModel _currentMouseDragOverStepViewModel;
        [ObservableProperty]
        string _originalVariableName;
        [ObservableProperty]
        StepViewModel _currentSelectedStepViewModel;
        [ObservableProperty]
        VariableManagerViewModel _variableManagerViewModel;
        public MainWindowViewModel()
        {
            //App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable("var1", @"CaliNine,2,OK,\r\n", VariableType.Text), VariableFrom.Local);
            //App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable("var3", new string[3] { "a", "b", "c" }, VariableType.Text), VariableFrom.Local);
            //App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable("var2", "b", VariableType.Numeric), VariableFrom.Local);
            //App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable("var4", new string[2] { "aaa", "bbb" }, VariableType.Text), VariableFrom.Local);
            //App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable("var5", new string[5] { "0", "1", "2", "3", "4" }, VariableType.Numeric), VariableFrom.Local);
            //string input = "@[var1].Split(,).Fetch([var3].IndexOf([var2])).Combine([var4].Fetch([var5].IndexOf(1)))";
            //VariableExpression testVar = new VariableExpression("testVar")
            //{
            //    Expressions = new List<string>() { input }
            //};
            //testVar.SetVariableManager(App.Current.Services.GetService<FlowManager>().VariableManager);
            //Variable eee = testVar.GetEquivalent();
            //VariableExpression ve = new VariableExpression()
            //{
            //    IsConst = false,
            //    Expression = "[var1].Split(,).Fetch(0).Subtract(1,1)",
            //    VariableType = VariableType.Text,
            //};
            //ve.SetVariableManager(App.Current.Services.GetService<FlowManager>().VariableManager);
            //Variable vvvv = ve.GetEquivalent();
            //string val = vvvv[0];

            //VariableExpression ve2 = new VariableExpression()
            //{
            //    IsConst = false,
            //    Expression = "([var5] * 3 - (4 + 1)).Fetch([var2])",
            //    VariableType = VariableType.Numeric,
            //};
            //ve2.SetVariableManager(App.Current.Services.GetService<FlowManager>().VariableManager);
            //Variable vvvv2 = ve2.GetEquivalent();
            //string val2 = vvvv2[0];
            if (false)
            {
                App.Current.Services.GetService<FlowManager>().SolutionName = "solution1";
                #region 加载资源变量
                foreach (var item in LocalMachine.Services.GetService<MachineResource<Axis, IAxis>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "Axis" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<Axis>(item.Value);
                }


                foreach (var item in LocalMachine.Services.GetService<MachineResource<Cylinder, IDigitalIO>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "Cylinder" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<Cylinder>(item.Value);
                }

                foreach (var item in LocalMachine.Services.GetService<MachineResource<Sensor, IDigitalIO>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "Sensor" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<Sensor>(item.Value);
                }

                foreach (var item in LocalMachine.Services.GetService<MachineResource<Pdo, IPdo>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "Pdo" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<Pdo>(item.Value);
                }

                foreach (var item in LocalMachine.Services.GetService<MachineResource<CommunicationClient, ICommunicationClient>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "CommunicationClient" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<CommunicationClient>(item.Value);
                }
                #endregion
                SerializableDictionary<string, Variable> vars = App.Current.Services.GetService<FlowManager>().VariableManager.ResourceVariables;
                #region 创建配方变量
                //配方点位
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("上料矩阵-X", new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("上料矩阵-Y", new string[] { "3", "3", "3", "6", "6", "6", "9", "9", "9" }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("Z安全位", new string[] { "0", "0" }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("Z安全位-Z1", new string[] { "0", }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("Z安全位-Z2", new string[] { "0", }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("Z取料高度", new string[] { "10", "12" }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("Z取料高度-Z1", new string[] { "10", }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("Z取料高度-Z2", new string[] { "12", }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("取料角度", new string[] { "1", "-1" }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("取料角度-R1", new string[] { "1", }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("取料角度-R2", new string[] { "-1", }, VariableType.Numeric));
                //配方参数                                       
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("吸嘴偏移X", new string[] { "0", "20" }, VariableType.Numeric));
                App.Current.Services.GetService<FlowManager>()?.CurrentRecipe.AddVariable(new Variable("吸嘴偏移Y", new string[] { "0", "0" }, VariableType.Numeric));

                App.Current.Services.GetService<FlowManager>()?.SaveRecipe("配方1");
                #endregion
                #region 创建flow
                FlowBase flow = new FlowBase("上料四轴", App.Current.Services.GetService<FlowManager>());
                //完成每个step的初始化 以及 每个step的变量注册
                flow.Open();
                flow.Init(out string errInfo);
                #region 创建信号
                flow.RegisterSignal("需要待测Tray");
                flow.RegisterSignal("放转盘完成");
                #endregion
                #region 创建流程变量
                //状态变量 - 流程用
                flow.AddVariable(new Variable("吸嘴有无料状态", new string[] { "无料", "无料" }, VariableType.Text) { Group = "上料四轴" });
                flow.AddVariable(new Variable("上料矩阵有无料状态", new string[] { "1", "1", "1", "1", "1", "1", "1", "1", "1" }, VariableType.Numeric) { Group = "上料四轴" });
                flow.AddVariable(new Variable("上料吸嘴气缸", new string[] { "吸嘴上下1", "吸嘴上下2" }, VariableType.Text) { Group = "上料四轴" });
                flow.AddVariable(new Variable("上料吸嘴真空", new string[] { "吸嘴真空1", "吸嘴真空2" }, VariableType.Text) { Group = "上料四轴" });
                flow.AddVariable(new Variable("上料吸嘴Z", new string[] { "Z1", "Z2" }, VariableType.Text) { Group = "上料四轴" });
                flow.AddVariable(new Variable("上料吸嘴R", new string[] { "R1", "R2" }, VariableType.Text) { Group = "上料四轴" });
                flow.AddVariable(new Variable("上料吸嘴真空感应", new string[] { "吸嘴1真空感应", "吸嘴2真空感应" }, VariableType.Text) { Group = "上料四轴" });
                flow.AddVariable(new Variable("上料吸嘴真空感应状态", new List<Variable>() { vars["吸嘴1真空感应.IsOn"], vars["吸嘴2真空感应.IsOn"], }, VariableType.Boolean) { Group = "上料四轴" });
                #endregion
                #region 创建流程步
                //两个都有料
                VariableJudge vj1 = new VariableJudge()
                {
                    SourceVariable = new VariableExpression("比较变量")
                    {
                        Expressions = new List<string>() { "@[上料四轴.吸嘴有无料状态].IndexOf(无料)" },
                        ExpressionDealVarType = VariableType.Text,
                    },
                    CompareVariable = new VariableExpression("比较值")
                    {
                        Expressions = new List<string>() { "-1" },
                    },
                    Sign = CompareSign.等于,
                    IsReverse = false,
                    IsEnable = true,
                    CompareIndex = 0,
                    Alias = "吸嘴都有料了",
                };
                //只要有没料的吸嘴
                VariableJudge vj2 = new VariableJudge()
                {
                    SourceVariable = new VariableExpression("比较变量")
                    {
                        Expressions = new List<string>() { "@[上料四轴.吸嘴有无料状态].Any(无料)" },
                        ExpressionDealVarType = VariableType.Text,
                    },
                    CompareVariable = new VariableExpression("比较值")
                    {
                        Expressions = new List<string>() { "true" }
                    },
                    Sign = CompareSign.等于,
                    IsReverse = false,
                    IsEnable = true,
                    CompareIndex = 0,
                    Alias = "还有吸嘴没料",
                };
                flow.AddStep("根据吸嘴料状态选择分支",
                            "SwitchStep",
                            flow.EntranceStep,
                            new SerializableDictionary<string, VariableExpression>(),
                            new List<VariableJudge>() { vj1, vj2 });

                vj2 = new VariableJudge()
                {
                    SourceVariable = new VariableExpression("比较变量")
                    {
                        Expressions = new List<string>() { "@[上料四轴.上料矩阵有无料状态].IndexOf(1)" },
                        ExpressionDealVarType = VariableType.Text,
                    },
                    CompareVariable = new VariableExpression("比较值")
                    {
                        Expressions = new List<string>() { "-1" }
                    },
                    Sign = CompareSign.不等于,
                    IsReverse = false,
                    IsEnable = true,
                    CompareIndex = 0,
                };
                flow.AddStep("判断Tray盘是否有料",
                            "IfStep",
                            flow.GetStep("根据吸嘴料状态选择分支.条件1"),
                            new SerializableDictionary<string, VariableExpression>(),
                            new List<VariableJudge>() { vj2 });

                VariableExpression ve1 = new VariableExpression("AxisNames")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "@[Z1]", "@[Z2]" }
                };
                VariableExpression ve2 = new VariableExpression("Position")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "@[Z安全位-Z1]", "@[Z安全位-Z2]" }
                };
                SerializableDictionary<string, VariableExpression> parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("AxisNames", ve1);
                parameters.Add("Position", ve2);
                flow.AddStep("Z轴抬起至安全位", "AxisMoveStep", flow.GetStep("判断Tray盘是否有料.满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("AxisNames")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "@[X]", "@[Y]", "@[R1]", "@[R2]" }
                };
                ve2 = new VariableExpression("Position")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "@[上料矩阵-X].Fetch([上料四轴.上料矩阵有无料状态].IndexOf(1))",
                        "@[上料矩阵-Y].Fetch([上料四轴.上料矩阵有无料状态].IndexOf(1))",
                        "@[取料角度-R1]",
                        "@[取料角度-R2]",
                    }
                };
                VariableExpression ve3 = new VariableExpression("Offset")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "@[吸嘴偏移X].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))",
                        "@[吸嘴偏移Y].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))",
                        "0",
                        "0",
                    }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("AxisNames", ve1);
                parameters.Add("Position", ve2);
                parameters.Add("Offset", ve3);
                flow.AddStep("XY移动至Tray盘取料位", "AxisMoveStep", flow.GetStep("判断Tray盘是否有料.满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("CylinderNames")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "@[上料四轴.上料吸嘴气缸].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))" }
                };
                ve2 = new VariableExpression("Status")
                {
                    ExpressionDealVarType = VariableType.Boolean,
                    Expressions = new List<string>() { "true" }
                };
                ve3 = new VariableExpression("TimeOut")
                {
                    ExpressionDealVarType = VariableType.Numeric,
                    Expressions = new List<string>() { "5000" }
                };
                VariableExpression ve4 = new VariableExpression("AsyncRun")
                {
                    ExpressionDealVarType = VariableType.Boolean,
                    Expressions = new List<string>() { "true" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("CylinderNames", ve1);
                parameters.Add("Status", ve2);
                parameters.Add("TimeOut", ve3);
                parameters.Add("AsyncRun", ve4);
                flow.AddStep("吸嘴气缸下降", "CylinderOperateStep", flow.GetStep("判断Tray盘是否有料.满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("AxisNames")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "@[上料四轴.上料吸嘴Z].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))" }
                };
                ve2 = new VariableExpression("Position")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "@[Z取料高度].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))",
                    }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("AxisNames", ve1);
                parameters.Add("Position", ve2);
                flow.AddStep("Z轴下降取料", "AxisMoveStep", flow.GetStep("判断Tray盘是否有料.满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("WaitVariable")
                {
                    ExpressionDealVarType = VariableType.Boolean,
                    Expressions = new List<string>() { "@[吸嘴气缸下降.Completed]" }
                };
                ve2 = new VariableExpression("WaitValue")
                {
                    ExpressionDealVarType = VariableType.Boolean,
                    Expressions = new List<string>()
                    {
                        "true",
                    }
                };
                ve3 = new VariableExpression("TimeOut")
                {
                    ExpressionDealVarType = VariableType.Numeric,
                    Expressions = new List<string>()
                    {
                        "5000",
                    }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("WaitVariable", ve1);
                parameters.Add("WaitValue", ve2);
                parameters.Add("TimeOut", ve3);
                flow.AddStep("等待气缸下降完成", "WaitStatusStep", flow.GetStep("判断Tray盘是否有料.满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("DelayTime")
                {
                    ExpressionDealVarType = VariableType.Numeric,
                    Expressions = new List<string>() { "500" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("DelayTime", ve1);
                flow.AddStep("下降后延时", "DelayStep", flow.GetStep("判断Tray盘是否有料.满足"), parameters, new List<VariableJudge>());

                vj1 = new VariableJudge()
                {
                    SourceVariable = new VariableExpression("比较变量")
                    {
                        Expressions = new List<string>() { "@[上料四轴.上料吸嘴真空感应状态].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))" },
                        ExpressionDealVarType = VariableType.Text,
                    },
                    CompareVariable = new VariableExpression("比较值")
                    {
                        Expressions = new List<string>() { "true" }
                    },
                    Sign = CompareSign.等于,
                    IsReverse = false,
                    IsEnable = true,
                    CompareIndex = 0,
                };
                flow.AddStep("判断真空",
                            "IfStep",
                            flow.GetStep("判断Tray盘是否有料.满足"),
                            new SerializableDictionary<string, VariableExpression>(),
                            new List<VariableJudge>() { vj1 });

                ve1 = new VariableExpression("CylinderNames")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "@[上料四轴.上料吸嘴真空].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))" }
                };
                ve2 = new VariableExpression("Status")
                {
                    ExpressionDealVarType = VariableType.Boolean,
                    Expressions = new List<string>() { "false" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("CylinderNames", ve1);
                parameters.Add("Status", ve2);
                flow.AddStep("报警后关真空", "CylinderOperateStep", flow.GetStep("判断真空.不满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("CylinderNames")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "@[上料四轴.上料吸嘴气缸].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))" }
                };
                ve2 = new VariableExpression("Status")
                {
                    ExpressionDealVarType = VariableType.Boolean,
                    Expressions = new List<string>() { "false" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("CylinderNames", ve1);
                parameters.Add("Status", ve2);
                flow.AddStep("报警后吸嘴气缸上升", "CylinderOperateStep", flow.GetStep("判断真空.不满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("AlarmInfo")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "真空未感应到，吸料失败！是否重试，点击 是 重试，点击 否 继续", }
                };
                ve2 = new VariableExpression("TryAgainStepName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "吸嘴气缸下降", }
                };
                //ve3 = new VariableExpression()
                //{
                //    VariableType = VariableType.Text,
                //    Expressions = new List<string>() { "吸嘴气缸下降", }
                //};
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("AlarmInfo", ve1);
                parameters.Add("TryAgainStepName", ve2);
                flow.AddStep("真空报警", "ShowWarnStep", flow.GetStep("判断真空.不满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("VariableName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "上料四轴.上料矩阵有无料状态" }
                };
                ve2 = new VariableExpression("UpdateIndex")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "@[上料四轴.上料矩阵有无料状态].IndexOf(1)",
                    }
                };
                ve3 = new VariableExpression("VariableValue")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "0",
                    }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("VariableName", ve1);
                parameters.Add("UpdateIndex", ve2);
                parameters.Add("VariableValue", ve3);
                flow.AddStep("更新上料Tray状态,设置吸不起的为物料", "UpdateVariableStep", flow.GetStep("判断真空.不满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("CylinderNames")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "@[上料四轴.上料吸嘴气缸].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))" }
                };
                ve2 = new VariableExpression("Status")
                {
                    ExpressionDealVarType = VariableType.Boolean,
                    Expressions = new List<string>() { "false" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("CylinderNames", ve1);
                parameters.Add("Status", ve2);
                flow.AddStep("吸嘴气缸上升", "CylinderOperateStep", flow.GetStep("判断真空.满足"), parameters, new List<VariableJudge>());

                vj1 = new VariableJudge()
                {
                    SourceVariable = new VariableExpression("比较变量")
                    {
                        Expressions = new List<string>() { "@[上料四轴.上料吸嘴真空感应状态].Fetch([上料四轴.吸嘴有无料状态].IndexOf(无料))" },
                        ExpressionDealVarType = VariableType.Text,
                    },
                    CompareVariable = new VariableExpression("比较值")
                    {
                        Expressions = new List<string>() { "true" }
                    },
                    Sign = CompareSign.等于,
                    IsReverse = false,
                    IsEnable = true,
                    CompareIndex = 0,
                };
                flow.AddStep("抬起后判断真空",
                            "IfStep",
                            flow.GetStep("判断真空.满足"),
                            new SerializableDictionary<string, VariableExpression>(),
                            new List<VariableJudge>() { vj1 });

                ve1 = new VariableExpression("VariableName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "上料四轴.吸嘴有无料状态", "上料四轴.上料矩阵有无料状态" }
                };
                ve2 = new VariableExpression("UpdateIndex")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "@[上料四轴.吸嘴有无料状态].IndexOf(无料)",
                        "@[上料四轴.上料矩阵有无料状态].IndexOf(1)",
                    }
                };
                ve3 = new VariableExpression("VariableValue")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "有料",
                        "0",
                    }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("VariableName", ve1);
                parameters.Add("UpdateIndex", ve2);
                parameters.Add("VariableValue", ve3);
                flow.AddStep("更新吸嘴和上料Tray状态", "UpdateVariableStep", flow.GetStep("抬起后判断真空.满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("AlarmInfo")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "真空未感应到，吸料失败！是否重试，点击 是 重试，点击 否 继续", }
                };
                ve2 = new VariableExpression("TryAgainStepName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "吸嘴气缸下降", }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("AlarmInfo", ve1);
                parameters.Add("TryAgainStepName", ve2);
                flow.AddStep("抬起后真空报警", "ShowWarnStep", flow.GetStep("抬起后判断真空.不满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("VariableName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "上料四轴.上料矩阵有无料状态" }
                };
                ve2 = new VariableExpression("UpdateIndex")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "@[上料四轴.上料矩阵有无料状态].IndexOf(1)",
                    }
                };
                ve3 = new VariableExpression("VariableValue")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>()
                    {
                        "0",
                    }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("VariableName", ve1);
                parameters.Add("UpdateIndex", ve2);
                parameters.Add("VariableValue", ve3);
                flow.AddStep("更新吸嘴和上料Tray状态,设置抬起后没吸起来的位置为无料", "UpdateVariableStep", flow.GetStep("抬起后判断真空.不满足"), parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("FlowName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "需要待测Tray" }
                };
                ve2 = new VariableExpression("SignalName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "上料四轴" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("FlowName", ve2);
                parameters.Add("SignalName", ve1);
                flow.AddStep("通知轨道流程需要待测Tray", "SetSignalStep", flow.GetStep("判断Tray盘是否有料.不满足"),
                             parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("FlowName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "轨道供待测Tray完成" }
                };
                ve2 = new VariableExpression("SignalName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "供Tray流程" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("FlowName", ve2);
                parameters.Add("SignalName", ve1);
                flow.AddStep("等待Tray到位", "WaitSignalStep", flow.GetStep("判断Tray盘是否有料.不满足"),
                             parameters, new List<VariableJudge>());
                #endregion
                #endregion
                #region 创建flow
                flow = new FlowBase("供Tray流程", App.Current.Services.GetService<FlowManager>());
                //完成每个step的初始化 以及 每个step的变量注册
                flow.Open();
                flow.Init(out errInfo);
                #region 创建信号
                flow.RegisterSignal("轨道供待测Tray完成");
                #endregion
                #region 创建流程变量

                #endregion
                #region 创建流程步
                ve1 = new VariableExpression("FlowName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "需要待测Tray" }
                };
                ve2 = new VariableExpression("SignalName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "上料四轴" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("FlowName", ve2);
                parameters.Add("SignalName", ve1);
                flow.AddStep("等待要Tray盘", "WaitSignalStep", flow.EntranceStep, parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("DelayTime")
                {
                    ExpressionDealVarType = VariableType.Numeric,
                    Expressions = new List<string>() { "10000" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("DelayTime", ve1);
                flow.AddStep("延时", "DelayStep", flow.EntranceStep, parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("FlowName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "轨道供待测Tray完成" }
                };
                ve2 = new VariableExpression("SignalName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "供Tray流程" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("FlowName", ve2);
                parameters.Add("SignalName", ve1);
                flow.AddStep("供Tray完成", "SetSignalStep", flow.EntranceStep, parameters, new List<VariableJudge>());
                #endregion
                #endregion
                #region 创建flow
                flow = new FlowBase("转盘流程", App.Current.Services.GetService<FlowManager>());
                //完成每个step的初始化 以及 每个step的变量注册
                flow.Open();
                flow.Init(out errInfo);
                #region 创建信号
                flow.RegisterSignal("转盘允许放料");
                #endregion
                #region 创建流程变量

                #endregion
                #region 创建流程步

                ve1 = new VariableExpression("FlowName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "转盘允许放料" }
                };
                ve2 = new VariableExpression("SignalName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "转盘流程" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("FlowName", ve2);
                parameters.Add("SignalName", ve1);
                flow.AddStep("通知上料四轴转盘允许放料", "SetSignalStep", flow.EntranceStep, parameters, new List<VariableJudge>());

                ve1 = new VariableExpression("DelayTime")
                {
                    ExpressionDealVarType = VariableType.Numeric,
                    Expressions = new List<string>() { "1000" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("DelayTime", ve1);
                flow.AddStep("延时", "DelayStep", flow.EntranceStep, parameters, new List<VariableJudge>());


                ve1 = new VariableExpression("FlowName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "放转盘完成" }
                };
                ve2 = new VariableExpression("SignalName")
                {
                    ExpressionDealVarType = VariableType.Text,
                    Expressions = new List<string>() { "上料四轴" }
                };
                parameters = new SerializableDictionary<string, VariableExpression>();
                parameters.Add("FlowName", ve2);
                parameters.Add("SignalName", ve1);
                flow.AddStep("等待放料完成", "WaitSignalStep", flow.EntranceStep, parameters, new List<VariableJudge>());
                #endregion
                #endregion
                #region 保存Solution
                App.Current.Services.GetService<FlowManager>().Save("solution1");
                #endregion
            }
            else
            {
                LocalMachine.Services.GetService<LogHelper>()?.Log(LogSource.App, "Load flow...", MessageLevel.Log);
                App.Current.Services.GetService<FlowManager>()?.Load("solution1");
                App.Current.Services.GetService<FlowManager>()?.Init(out string errInfo);
                App.Current.Services.GetService<FlowManager>()?.LoadRecipe("配方1");
                #region 加载资源变量
                foreach (var item in LocalMachine.Services.GetService<MachineResource<Axis, IAxis>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "Axis" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<Axis>(item.Value);
                }


                foreach (var item in LocalMachine.Services.GetService<MachineResource<Cylinder, IDigitalIO>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "Cylinder" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<Cylinder>(item.Value);
                }

                foreach (var item in LocalMachine.Services.GetService<MachineResource<Sensor, IDigitalIO>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "Sensor" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<Sensor>(item.Value);
                }

                foreach (var item in LocalMachine.Services.GetService<MachineResource<Pdo, IPdo>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "Pdo" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<Pdo>(item.Value);
                }

                foreach (var item in LocalMachine.Services.GetService<MachineResource<CommunicationClient, ICommunicationClient>>().Value)
                {
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariable(new Variable(item.Key, item.Key, VariableType.Text) { Group = "CommunicationClient" }, VariableFrom.Resource);
                    App.Current.Services.GetService<FlowManager>().VariableManager.AddVariablesFromResource<CommunicationClient>(item.Value);
                }
                #endregion
            }

            VariableManagerViewModel = new VariableManagerViewModel(App.Current.Services.GetService<FlowManager>());

            FlowViewModels = new ObservableCollection<FlowViewModel>(App.Current.Services.GetService<FlowManager>().Flows.Values.Select(f => new FlowViewModel(f)));
            flowEntranceStepViewModels = App.Current.Services.GetService<FlowManager>()!
                                         .Flows!
                                         .ToDictionary(pair => pair.Key,
                                                       pair => new ObservableCollection<StepViewModel>()
                                                       {
                                                           new StepViewModel(pair.Value.EntranceStep)
                                                       });
            if (FlowViewModels.Count > 0)
                CurrentSelectedFlow = FlowViewModels[0];

            Dictionary<string, IStep> stepOperators = LocalMachine.Services.GetService<AssemblyHelper>()!.GetInstance<IStep>();
            StepGroups = new ObservableCollection<StepInfoGroup>();
            foreach (var item in stepOperators)
            {
                StepInfo si = item.Value.GetInfo();
                StepInfoGroup? sig = StepGroups.FirstOrDefault(s => s.GroupName.Equals(si.Group.ToString()));
                if (sig != null)
                {
                    sig.StepInfos.Add(si);
                }
                else
                    StepGroups.Add(new StepInfoGroup(si.Group.ToString(), new ObservableCollection<StepInfo>() { si }));
            }

            //Task.Run(() =>
            //{
            //    int i = 0;
            //    while(true)
            //    {
            //        LocalMachine.Services.GetService<MachineResource<Axis, IAxis>>().Value["X"].ConvertRate = i++;

            //        Thread.Sleep(10);
            //    }
            //});
        }
        [RelayCommand]
        void FlowTabChanged(object item)
        {
            if (item as FlowViewModel == null) return;
            EntranceStepViewModel = flowEntranceStepViewModels[((FlowViewModel)item).FlowName];
        }
        [RelayCommand(CanExecute = nameof(CanStartExecute))]
        void flowStart()
        {
            if (!App.Current.Services.GetService<FlowManager>()!.Compile(out string errInfoCompile))
            {
                System.Windows.MessageBox.Show(errInfoCompile);
                CanStartExecute = true;
                return;
            }
            if (!App.Current.Services.GetService<FlowManager>()!.Prepare(out string errInfo))
            {
                System.Windows.MessageBox.Show(errInfo);
                CanStartExecute = true;
                return;
            }
            CanStartExecute = false;
            CanStepExecute = false;
            App.Current.Services.GetService<FlowManager>()!.Start();
            IsAllowEdit = false;
            CanPauseExecute = true;
            CanStopExecute = true;
        }
        [RelayCommand(CanExecute = nameof(CanPauseExecute))]
        async void flowPause()
        {
            CanPauseExecute = false;
            CanStopExecute = false;
            App.Current.Services.GetService<FlowManager>()!.Pause();
            await Task.Run(() =>
            {
                while (!App.Current.Services.GetService<FlowManager>()!.AllFlowPaused)
                {
                    Thread.Sleep(2);
                }
                return true;
            });
            IsAllowEdit = true;
            CanStartExecute = true;
            CanStopExecute = true;
            CanStepExecute = true;
        }
        [RelayCommand(CanExecute = nameof(CanStopExecute))]
        async void flowStop()
        {
            CanStopExecute = false;
            CanPauseExecute = false;
            App.Current.Services.GetService<FlowManager>()!.Stop();
            await Task.Run(() =>
            {
                while (!App.Current.Services.GetService<FlowManager>()!.AllFlowStopped)
                {
                    Thread.Sleep(2);
                }
                return true;
            });
            App.Current.Services.GetService<FlowManager>()!.ResetBreak();
            App.Current.Services.GetService<FlowManager>()!.ResetAllSignals();
            App.Current.Services.GetService<FlowManager>()!.ResetVariables();
            foreach (var item in flowEntranceStepViewModels.Values)
            {
                if (item != null && item.Count > 0)
                {
                    item[0].ResetViewModel();
                }
            }
            CanStartExecute = true;
            CanStepExecute = true;
        }
        [RelayCommand(CanExecute = nameof(CanStepExecute))]
        async void flowStep()
        {
            App.Current.Services.GetService<FlowManager>()!.Step();
            flowStart();
            Thread.Sleep(50);
            await Task.Run(() =>
            {
                while (!App.Current.Services.GetService<FlowManager>()!.AllFlowPaused)
                {
                    Thread.Sleep(2);
                }
                return true;
            });
            CanStartExecute = true;
            CanStopExecute = true;
            CanStepExecute = true;
        }
        [RelayCommand(CanExecute = "IsAllowEdit")]
        void AddFlow()
        {
            string tempName = "";
            for (int i = 0; i < 999; i++)
            {
                tempName = $"flow{i}";
                if (!App.Current.Services.GetService<FlowManager>()!.Flows!.ContainsKey(tempName))
                    break;
            }
            FlowBase flow = new FlowBase(tempName, App.Current.Services.GetService<FlowManager>()!);
            flow.Open();
            flow.Init(out string errInfo);
            flowEntranceStepViewModels.Add(tempName, new ObservableCollection<StepViewModel>() { new StepViewModel(flow.EntranceStep) });
            CurrentSelectedFlow = new FlowViewModel(flow);
            FlowTabChanged(CurrentSelectedFlow);
            App.Current.Services.GetService<FlowManager>()!.Save("solution1");
        }
        [RelayCommand(CanExecute = "IsAllowEdit")]
        void RemoveFlow()
        {
            if (CurrentSelectedFlow == null)
            {
                System.Windows.MessageBox.Show("请选中流程");
                return;
            }

            flowEntranceStepViewModels.Remove(CurrentSelectedFlow.FlowName);
            App.Current.Services.GetService<FlowManager>()!.Flows!.Remove(CurrentSelectedFlow.FlowName);
            if (FlowViewModels.Count > 0)
            {
                CurrentSelectedFlow = FlowViewModels[0];
                FlowTabChanged(CurrentSelectedFlow);
            }
            App.Current.Services.GetService<FlowManager>()!.Save("solution1");
        }
        [RelayCommand]
        void StepSelectionChanged(object obj)
        {
            if (obj == null)
                return;
            Step step = ((StepViewModel)obj).GetStep();
            if (step != null)
            {
                //StepUI = step.GetOperator().GetForm() as UserControl;
            }
        }
        [RelayCommand]
        void FlowTreeKeyDown(object eventArgs)
        {
            KeyEventArgs e = (KeyEventArgs)eventArgs;
            if (e.KeyStates == Keyboard.GetKeyStates(Key.S) && Keyboard.Modifiers == ModifierKeys.Control)
            {
                App.Current.Services.GetService<FlowManager>().Save("solution1");
                Growl.Info("保存成功!");
            }
        }
        [RelayCommand]
        void AddStepFromStepMenu(object obj)
        {
            StepInfo si = obj as StepInfo;
            FlowBase flow = App.Current.Services.GetService<FlowManager>().Flows[CurrentSelectedFlow.FlowName];
            //如果是条件步 有条件结点 需要到条件节点后面加
            if (_currentMouseDragOverStep.Conditions?.Count > 0)
            {

            }
            //如果是条件节点,直接添加children
            else if (_currentMouseDragOverStep.IsConditionNode)
            {
                string stepName = flow.CreateStepName($"{si.StepName}Step");
                if (flow.GetSteps().FirstOrDefault(s => s.Description.Equals(stepName)) != null)
                    throw new Exception("已存在同名变量");
                Step step = new Step(stepName, $"{si.StepName}Step", flow);
                step.SetOperator(Activator.CreateInstance(App.Current.Services.GetService<FlowManager>().GetStepOperators()[$"{si.StepName}Step"]) as IStep);
                flow.AddStep(step, _currentMouseDragOverStep, true);
                _currentMouseDragOverStepViewModel.AddChildren(new StepViewModel(step), true);
                //#region 保存Solution
                //App.Current.Services.GetService<FlowManager>().Save("solution1");
                //#endregion
            }
            else
            {
                //是普通节点，则加到该节点的父步骤去
                string stepName = flow.CreateStepName($"{si.StepName}Step");
                if (flow.GetSteps().FirstOrDefault(s => s.Description.Equals(stepName)) != null)
                    throw new Exception("已存在同名变量");
                Step step = new Step(stepName, $"{si.StepName}Step", flow);
                step.SetOperator(Activator.CreateInstance(App.Current.Services.GetService<FlowManager>().GetStepOperators()[$"{si.StepName}Step"]) as IStep);
                int insertIndex = _currentMouseDragOverStep.GetParent().Children.IndexOf(_currentMouseDragOverStep) + 1;
                flow.AddStep(step, _currentMouseDragOverStep.GetParent(), true, insertIndex);
                _currentMouseDragOverStepViewModel.Parent.AddChildren(new StepViewModel(step), true, insertIndex);
            }
        }
        [RelayCommand]
        void StepDelete(object obj)
        {
            if (CurrentSelectedStepViewModel != null)
            {
                FlowBase flow = App.Current.Services.GetService<FlowManager>().Flows[CurrentSelectedFlow.FlowName];
                Step step = CurrentSelectedStepViewModel.GetStep();
                StepViewModel father = CurrentSelectedStepViewModel.Parent;
                if (step.Children != null && step.Children.Count > 0)
                {
                    if (System.Windows.MessageBox.Show("当前步存在子步，是否继续", "删除步", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
                    {
                        return;
                    }
                }
                //流程步删掉
                flow.DeleteStep(step);
                //viewmodel删掉
                father.Children.Remove(CurrentSelectedStepViewModel);
            }
        }
        [RelayCommand]
        void DragOverStep(object obj)
        {
            StepViewModel svm = obj as StepViewModel;
            if (svm != null)
            {
                _currentMouseDragOverStepViewModel = svm;
                _currentMouseDragOverStep = svm.GetStep();
            }
        }
        [RelayCommand]
        void VariableLinkButtonClick(object obj)
        {
            if (_variableTreeView != null && _variableTreeView.IsInitialized && _variableTreeView.IsVisible)
            {
                if (_variableTreeView.WindowState == System.Windows.WindowState.Minimized)
                    _variableTreeView.WindowState = System.Windows.WindowState.Normal;
                _variableTreeView.Activate();
            }
            else
            {
                _variableTreeView = new VariableTreeView();
                _variableTreeView.DataContext = VariableManagerViewModel;
                _variableTreeView.VariableSelectionChangedCommand = SelectedVariableChangedCommand;
                _variableTreeView.Show();
            }
        }
        [RelayCommand]
        void VariableExpButtonClick(object obj)
        {

        }
        [RelayCommand]
        void WindowClose()
        {
            //close all windows
            foreach (System.Windows.Window window in Application.Current.Windows)
            {
                if (window != Application.Current.MainWindow)
                {
                    window.Close();
                }
            }
        }
        [RelayCommand]
        void SelectedVariableChanged(object obj)
        {
            if (obj is VariableViewModel)
            {
                VariableViewModel vvm = obj as VariableViewModel;
                VariableManagerViewModel.SelectedVariableName = vvm.Name;
                OriginalVariableName = vvm.IsLocal ? $"[{vvm.GetVariable().Group}.{vvm.Name}]" : $"[{vvm.Name}]";
            }
        }
        [RelayCommand]
        void openVariable()
        {
            VariableControl varCtrl = new VariableControl();
            varCtrl.Show();
        }
        [RelayCommand]
        void VariableGroupChanged(object obj)
        {
            VariableManagerViewModel.ChangeGroupSelection(obj as VariableGroup);
        }
        
    }
}
